package com.server.utils;

import com.server.Tcp.TcpTransitMsgString;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.ResourceBundle;

/**
 * 工具类
 */
@Slf4j
public class TcpSocket {
    /**
     * 功能：关流和关socket
     * @param bi 缓冲输入流
     * @param bo 缓冲输出流
     * @param server 服务端
     * @param client 客户端
     */
    public static void closeSAndC(BufferedReader br,BufferedWriter bw, BufferedInputStream bi, BufferedOutputStream bo, ServerSocket server, Socket client ){
        if (br!=null){
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bw!=null){
            try {
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (server!=null){
            try {
                server.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (client!=null){
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bi!=null){
            try {
                bi.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bo!=null){
            try {
                bo.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void closeSAndC(BufferedInputStream bi, BufferedOutputStream bo){
        closeSAndC(null,null,bi,bo,null,null);
    }
    public static void closeSAndC(Socket socket,BufferedInputStream bi, BufferedOutputStream bo){
        closeSAndC(null,null,bi,bo,null,socket);
    }
    //写字符串数据
    public static void writeData(String data,BufferedOutputStream bw){
        try {
            bw.write(data.getBytes());
            bw.flush();
        } catch (IOException e) {
            log.info(e.getMessage());
        }
    }
    //写字节数据
    public static void writeData(byte[] data,BufferedOutputStream bo){
        try {
            bo.write(data);
            bo.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //需要发送给节点的信息条数
    private static final int count=3;
    //资源绑定器对nodeIp所用的变量
    private static final ResourceBundle bundle=ResourceBundle.getBundle("static/fixedresources/nodeIp");
    private static String[] impartNode=null;
    private static int imNode;
    private static boolean isOver=false;
    private static boolean[] var=new boolean[4];
    private static double[] traffic=new double[4];
    /**
     * 功能：根据接收到的数据进行计算
     * @return 返回需要发送的数据数组
     */
    public static String[] calculate(String data){
        //将接收到的数据按规定的格式进行分隔处理()
        String[] datas=data.split("[,|，| ]");
        if (datas.length!=count){
            System.out.println(Arrays.toString(datas));
            System.out.println("输入格式有误，不予处理");
            return null;
        }
        int node=Integer.parseInt(datas[0])-1;
        if (impartNode==null) {
            imNode=node;
            impartNode=new String[2];
            impartNode[0] = datas[1];
            impartNode[1] = datas[2];
            //找到与当前节点非零的节点发送请求数据
            double[][] distance = FixedParam.getDistance();
            for (int i=0;i<4;i++){
                if (distance[node][i]!=0){
                    try {
                        var[i]=true;
                        TcpTransitMsgString.transitMsg("给我数据",i+1);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return null;
        }
        //综合矩阵
        double[] synthesis;
        //概率矩阵
        double[] probability = new double[0];
        if (var[node]){
            traffic[node]=Integer.parseInt(datas[1]);
            var[node]=false;
            if (var[0]||var[1]||var[2]||var[3]){
                return null;
            }else {
                synthesis= FixedParam.add(FixedParam.getSynthesis()[imNode], FixedParam.multiply(traffic, FixedParam.λ));
                probability=FixedParam.initProbability(synthesis);
                isOver=true;
            }
        }
        if (isOver) {
            isOver=false;
            //优先因子矩阵
            double[] pri;
            //捕捉节点身份信息输入错误导致的错误
            try {
                pri = getPri(probability);
            } catch (NumberFormatException e) {
                System.out.println("节点信息输入错误");
                return null;
            }
            //待发送的数据数组
            String[] needSend = new String[count];
            for (int i = 0; i < count; i++) {
                //优先级因子+车牌号+方向
                needSend[i] = pri[i] + datas[1] + datas[count - 1] + ",";
            }
            var=new boolean[4];
            traffic=new double[4];
            impartNode=null;
            return needSend;
        }
       return null;
    }
    /**
     * 功能：计算优先级因子
     * @param num 概率矩阵
     * @return 优先级因子矩阵
     */
    private static double[] getPri(double[] num){
        double[] pri=new double[num.length];
        //最大值的下标
        int maxIndex=-1;
        //存储最大值
        double max=-1;
        //将最大值的下标所在值赋为2，0为0，其余为1
        for (int i=0;i<num.length;i++){
            if (num[i]==0){
                pri[i]=0;
            }else {
                if (num[i]>max){
                    max=num[i];
                    maxIndex=i;
                }
                pri[i]=1;
            }
        }
        pri[maxIndex]=2;
        return pri;
    }

    /**
     * 功能：得到properties中的变量值（获取配置文件时，不能加后缀，加了报错）
     * @param key 需要提取的值的key，一个key对应一个value
     * @return 返回所给key对应的value
     */
    public static String getFixedRes(String key){
        //创建资源对象
        return bundle.getString(key);
    }
}
